# -*- coding: UTF-8 -*-
"""
使用主线程串行运行。

注意：配置文件里不要包含特殊符号：%
date:2019/3/11
"""
from telnetlib import Telnet
import configparser
import datetime
import os
import sys
import re

bash_path = 'D:\\dev\\switch\\'

sys_date = str(datetime.datetime.now()).split('.')[0].replace(':', '-')
export_path = bash_path + sys_date + '\\'
config_file = bash_path + 'switch2.ini'
output_way = 'file'          # 输出方式有'sys'和'file'。


class MyTelnet(Telnet):
    def __init__(self, host_, port_, user, passwd):
        super().__init__(host_, port_, timeout=2)
        # self.write(b' \n')
        self.write(user.encode())
        self.write(b'\n')
        self.write(passwd.encode())
        self.write(b'\n')
        self.expect([b'<.+>'])
        self.write(b'dis cu\n')

    def fill_rawq(self):
        if self.irawq >= len(self.rawq):
            self.rawq = b''
            self.irawq = 0
        buf = self.sock.recv(1000)      # 对接收的数据容量扩大，以避免一行不能完整的输出。
        self.msg("recv %r", buf)
        self.eof = (not buf)
        self.rawq = self.rawq + buf

    def run(self, f):
        """
        一直把设备内容全部输出为止。
        :param f: 文本输出。
        :return:
        """
        while True:
            msg = self.read_some()
            if re.search(b'<.+>', msg) and len(msg.decode()) < 20:     # 搜到<*>的内容就代表本次全部输出结束，跳出循环。
                break
            if b'\x1b[42D                                          \x1b[42D' in msg:    # 遇到特殊符号跳出本次循环。
                continue
            if b'More' in msg:              # 遇到more时继续输出。
                self.write(b' \n')
                continue
            _msg = msg.decode().replace('\n', '')
            print(_msg)

            if f:
                f.write(_msg)
        f.close()


class SwitchConfig:
    def __init__(self, config):
        self.config = configparser.ConfigParser()
        self._format = 'utf-8'
        self.config.read(config, self._format)


    def _get_info(self):
        """ 从配置文件获取设备登录信息。"""
        if not os.path.exists(config_file):
            print('no switch.ini file')
            sys.exit()

        for configs in self.config.sections():
            try:
                # return 4 value for for loop.
                yield self.config[configs]['ip'], self.config[configs]['user'], self.config[configs]['pwd'], \
                      self.config[configs]['des']
            except configparser.InterpolationSyntaxError:
                print("error in get : " + str(self.config[configs]))

    def _use_login(self):
        """
        这是一个公共的方法，用装饰器方式来达到代码复用的作用。
        :return:
        """
        if output_way == 'file':
            if not os.path.exists(export_path):
                os.mkdir(export_path)
        i = 0
        for value in self._get_info():
            self.ip, self.user, self.pwd, self.des = value
            # print('*' * 30)
            # i += 1
            # print(value)
            # print(i)
            # print('*' * 30)

            try:
                self.tel = MyTelnet(self.ip, 23, self.user, self.pwd)
            except Exception:
                print('error in ' + self.des)
                continue

            f = None
            if output_way == 'file':
                file_name = export_path + self.des + '.txt'
                f = open(file_name, 'w')
            self.tel.run(None if f is None else f)

    def login(self):
        self._use_login()


SwitchConfig(config_file).login()
